/*
@(#)WechatpayService   2024-09-23
 
Copyright (c) 2011-2024 杭州湖畔网络技术有限公司 
保留所有权利 
本软件为杭州湖畔网络技术有限公司所有及包含机密信息，须遵守其相关许可证条款进行使用。
Copyright (c) 2011-2024 HUPUN Network Technology CO.,LTD.
All rights reserved.
This software is the confidential and proprietary information of HUPUN
Network Technology CO.,LTD("Confidential Information").  You shall not
disclose such Confidential Information and shall use it only in
accordance with the terms of the license agreement you entered into with HUPUN.
Website：http://www.hupun.com
*/
package org.obp.pay.third.wechat.service;

import cn.hutool.core.date.DateUtil;
import com.alibaba.fastjson.JSON;
import com.wechat.pay.java.service.payments.app.AppServiceExtension;
import com.wechat.pay.java.service.payments.h5.H5Service;
import com.wechat.pay.java.service.payments.h5.model.H5Info;
import com.wechat.pay.java.service.payments.h5.model.SceneInfo;
import com.wechat.pay.java.service.payments.jsapi.JsapiServiceExtension;
import com.wechat.pay.java.service.payments.nativepay.NativePayService;
import com.wechat.pay.java.service.refund.RefundService;
import com.wechat.pay.java.service.refund.model.AmountReq;
import com.wechat.pay.java.service.refund.model.CreateRequest;
import com.wechat.pay.java.service.refund.model.Refund;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.time.DateUtils;
import org.obp.pay.domain.PaymentOrder;
import org.obp.pay.third.wechat.config.WechatpayConfig;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.math.BigDecimal;

/**
 * @author: Jackey 2024/9/23
 */
@Slf4j
@Component
public class WechatpayService {

    @Autowired
    private WechatpayConfig wechatpayConfig;

    /**
     * 微信支付 - Native
     *
     * @param paymentOrder
     * @return
     */
    public com.wechat.pay.java.service.payments.nativepay.model.PrepayResponse executePayNative(PaymentOrder paymentOrder) {

        NativePayService service = new NativePayService.Builder().config(wechatpayConfig.getWxPayConfig()).build();

        com.wechat.pay.java.service.payments.nativepay.model.PrepayRequest request
                = new com.wechat.pay.java.service.payments.nativepay.model.PrepayRequest();
        request.setAppid(wechatpayConfig.getAppId_app());
        request.setMchid(wechatpayConfig.getMerchantId());
        request.setNotifyUrl(wechatpayConfig.getDomain() + wechatpayConfig.getPayNotifyUrl());
        request.setOutTradeNo(paymentOrder.getOrderSn());
        request.setDescription(paymentOrder.getOrderTitle());
        com.wechat.pay.java.service.payments.nativepay.model.Amount amount
                = new com.wechat.pay.java.service.payments.nativepay.model.Amount();
        amount.setTotal(paymentOrder.getPaidAmount().multiply(new BigDecimal(100)).intValue());
        amount.setCurrency("CNY");
        request.setAmount(amount);
        request.setTimeExpire(DateUtil.format(DateUtils.addMinutes(paymentOrder.getOrderTime(), wechatpayConfig.getExpiredMinutes()), "yyyy-MM-dd'T'HH:mm:ss") + "+08:00");

        log.info("微信Native支付接口-请求: " + JSON.toJSONString(request));

        com.wechat.pay.java.service.payments.nativepay.model.PrepayResponse response
                = service.prepay(request);

        log.info("微信Native支付接口-响应: " + JSON.toJSONString(response));

        return response;
    }

    /**
     * 微信支付 - H5
     *
     * @param paymentOrder
     * @param payerClientIp
     * @param h5Info
     * @return
     */
    public com.wechat.pay.java.service.payments.h5.model.PrepayResponse executePayH5(PaymentOrder paymentOrder, String payerClientIp, H5Info h5Info) {

        H5Service service = new H5Service.Builder().config(wechatpayConfig.getWxPayConfig()).build();

        com.wechat.pay.java.service.payments.h5.model.PrepayRequest request
                = new com.wechat.pay.java.service.payments.h5.model.PrepayRequest();
        request.setAppid(wechatpayConfig.getAppId_app());
        request.setMchid(wechatpayConfig.getMerchantId());
        request.setNotifyUrl(wechatpayConfig.getDomain() + wechatpayConfig.getPayNotifyUrl());
        request.setOutTradeNo(paymentOrder.getOrderSn());
        request.setDescription(paymentOrder.getOrderTitle());
        com.wechat.pay.java.service.payments.h5.model.Amount amount
                = new com.wechat.pay.java.service.payments.h5.model.Amount();
        amount.setTotal(paymentOrder.getPaidAmount().multiply(new BigDecimal(100)).intValue());
        amount.setCurrency("CNY");
        request.setAmount(amount);
        request.setTimeExpire(DateUtil.format(DateUtils.addMinutes(paymentOrder.getOrderTime(), wechatpayConfig.getExpiredMinutes()), "yyyy-MM-dd'T'HH:mm:ss") + "+08:00");

        SceneInfo sceneInfo = new SceneInfo();
        sceneInfo.setPayerClientIp(payerClientIp);
        sceneInfo.setH5Info(h5Info);
        request.setSceneInfo(sceneInfo);

        log.info("微信H5支付接口-请求: " + JSON.toJSONString(request));

        com.wechat.pay.java.service.payments.h5.model.PrepayResponse response
                = service.prepay(request);

        log.info("微信H5支付接口-响应: " + JSON.toJSONString(response));

        return response;
    }

    /**
     * 微信支付 - APP
     *
     * @param paymentOrder
     * @return
     */
    public com.wechat.pay.java.service.payments.app.model.PrepayWithRequestPaymentResponse executePayApp(PaymentOrder paymentOrder) {

        AppServiceExtension service = new AppServiceExtension.Builder().config(wechatpayConfig.getWxPayConfig()).build();

        com.wechat.pay.java.service.payments.app.model.PrepayRequest request
                = new com.wechat.pay.java.service.payments.app.model.PrepayRequest();
        request.setAppid(wechatpayConfig.getAppId_app());
        request.setMchid(wechatpayConfig.getMerchantId());
        request.setNotifyUrl(wechatpayConfig.getDomain() + wechatpayConfig.getPayNotifyUrl());
        request.setOutTradeNo(paymentOrder.getOrderSn());
        request.setDescription(paymentOrder.getOrderTitle());
        com.wechat.pay.java.service.payments.app.model.Amount amount
                = new com.wechat.pay.java.service.payments.app.model.Amount();
        amount.setTotal(paymentOrder.getPaidAmount().multiply(new BigDecimal(100)).intValue());
        amount.setCurrency("CNY");
        request.setAmount(amount);
        request.setTimeExpire(DateUtil.format(DateUtils.addMinutes(paymentOrder.getOrderTime(), wechatpayConfig.getExpiredMinutes()), "yyyy-MM-dd'T'HH:mm:ss") + "+08:00");

        log.info("微信APP支付接口-请求: " + JSON.toJSONString(request));

        com.wechat.pay.java.service.payments.app.model.PrepayWithRequestPaymentResponse response
                = service.prepayWithRequestPayment(request);

        log.info("微信APP支付接口-响应: " + JSON.toJSONString(response));

        return response;
    }

    /**
     * 微信支付 - MA
     *
     * @param paymentOrder
     * @param openId
     * @return
     */
    public com.wechat.pay.java.service.payments.jsapi.model.PrepayWithRequestPaymentResponse executePayMa(PaymentOrder paymentOrder, String openId) {

        JsapiServiceExtension service = new JsapiServiceExtension.Builder().config(wechatpayConfig.getWxPayConfig()).build();

        com.wechat.pay.java.service.payments.jsapi.model.PrepayRequest request
                = new com.wechat.pay.java.service.payments.jsapi.model.PrepayRequest();
        request.setAppid(wechatpayConfig.getAppId_ma());
        request.setMchid(wechatpayConfig.getMerchantId());
        request.setNotifyUrl(wechatpayConfig.getDomain() + wechatpayConfig.getPayNotifyUrl());
        com.wechat.pay.java.service.payments.jsapi.model.Payer payer
                = new com.wechat.pay.java.service.payments.jsapi.model.Payer();
        payer.setOpenid(openId);
        request.setPayer(payer);
        request.setOutTradeNo(paymentOrder.getOrderSn());
        request.setDescription(paymentOrder.getOrderTitle());
        com.wechat.pay.java.service.payments.jsapi.model.Amount amount
                = new com.wechat.pay.java.service.payments.jsapi.model.Amount();
        amount.setTotal(paymentOrder.getPaidAmount().multiply(new BigDecimal(100)).intValue());
        amount.setCurrency("CNY");
        request.setAmount(amount);
        request.setTimeExpire(DateUtil.format(DateUtils.addMinutes(paymentOrder.getOrderTime(), wechatpayConfig.getExpiredMinutes()), "yyyy-MM-dd'T'HH:mm:ss") + "+08:00");

        log.info("微信小程序支付接口-请求: " + JSON.toJSONString(request));

        com.wechat.pay.java.service.payments.jsapi.model.PrepayWithRequestPaymentResponse response
                = service.prepayWithRequestPayment(request);

        log.info("微信小程序支付接口-响应: " + JSON.toJSONString(response));

        return response;
    }

    /**
     * 微信支付退款
     *
     * @param orderSn
     * @param refundSn
     * @param refundAmount
     * @return
     */
    public Refund executeRefund(String orderSn, String refundSn, BigDecimal refundAmount, BigDecimal payAmount) {

        RefundService service = new RefundService.Builder().config(wechatpayConfig.getWxPayConfig()).build();

        CreateRequest request = new CreateRequest();
        request.setOutTradeNo(orderSn);
        request.setOutRefundNo(refundSn);
        request.setNotifyUrl(wechatpayConfig.getDomain() + wechatpayConfig.getRefundNotifyUrl());
        AmountReq amountReq = new AmountReq();
        amountReq.setRefund(refundAmount.multiply(new BigDecimal(100)).longValue());
        amountReq.setTotal(payAmount.multiply(new BigDecimal(100)).longValue());
        amountReq.setCurrency("CNY");
        request.setAmount(amountReq);

        log.info("微信支付退款接口-请求: " + JSON.toJSONString(request));

        Refund refund = service.create(request);

        log.info("微信支付退款接口-响应: " + JSON.toJSONString(refund));

        return refund;
    }

    public void setWechatpayConfig(WechatpayConfig wechatpayConfig) {
        this.wechatpayConfig = wechatpayConfig;
    }

}